<template>
  <view class="content">
    <view class="tools-menu">
      <view class="file-menu-box">

        <el-popover placement="bottom" :width="400" trigger="hover">
          <template #reference>
            <view style="width: 70rpx">
              <view class="file-menu">
                <svg role="img" aria-label="menu" focusable="false" data-icon="menu" aria-hidden="true" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="gd_design_icon gd_design_icon-menu"><path fill-rule="evenodd" clip-rule="evenodd" d="M4 6.75L20 6.75V5.25H4V6.75ZM20 12.75H4V11.25H20V12.75ZM20 18.75H4V17.25H20V18.75Z" fill="currentColor"></path></svg>
              </view>
            </view>
          </template>
          <view class="menu-list">
            <view class="menu-item" @click="showTemplates = true">
              <view>选择模板</view>
              <el-drawer v-model="showTemplates" direction="ltr">
                <el-space wrap class="template-list" :size="'large'">
                  <el-card class="template-item" v-for="(item,index) in templateDatas" :key="index" >
                    <template #header>
                      <div class="card-header">
                        <span>模板{{index + 1}}（{{item.name}}）</span>
                        <el-button class="button" type="primary" text @click="selectedTemplate(item)">载入</el-button>
                      </div>
                    </template>
                    <el-image :src="item.thumbnail"></el-image>
                  </el-card>
                </el-space>
              </el-drawer>
            </view>
            <view class="menu-item" @click="loadPsd">加载psd</view>
            <view class="menu-item" @click="importData">导入数据</view>
            <view class="menu-item" @click="exportData">导出数据</view>
            <view class="menu-item" @click="downImageData">导出图片</view>
          </view>
        </el-popover>
      </view>
      <view class="edit-width-height" :style="{paddingLeft: leftOpen? '690rpx':'50rpx'}">
        <view>画布大小</view>
        <view class="edit-input">

          <view>宽：
            <input type="text" @confirm="setCanvasSize" :value="drawData.width" @update:modelValue="drawData.width = +$event" placeholder="请输入宽">
          </view>
          <view>高：
            <input type="text" @confirm="setCanvasSize" :value="drawData.height" @update:modelValue="drawData.height = +$event" placeholder="请输入高">
          </view>
          <view style="margin-left: 20px;">
            显示百分比：<el-input-number @change="setCanvasSize" :step="10" :min="10" v-model="showScaleInput" placeholder="倍数"></el-input-number>
          </view>

          <view style="cursor:pointer;color: #007aff" @click="setCanvasSize">确定</view>
          <view style="cursor:pointer;color: #007aff" @click="adaptiveShow">自适应</view>
          <view style="cursor:pointer;margin-left: 20rpx;width: 40rpx" :style="{color: curIndex === 0 ? '#999' : '#007aff'}" @click="undo">
            <svg role="img" aria-label="revoke" focusable="false" data-icon="revoke" aria-hidden="true" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="gd_design_icon gd_design_icon-revoke"><path d="M8.58962 4.53447L5.83094 7.25018L14.5001 7.25018C17.9518 7.25018 20.75 10.0483 20.75 13.5001C20.75 16.9518 17.9518 19.75 14.5001 19.75H8.99761V18.25H14.5001C17.1234 18.25 19.25 16.1234 19.25 13.5001C19.25 10.8768 17.1234 8.75018 14.5001 8.75018L5.83094 8.75018L8.58962 11.4659L7.53732 12.5348L2.93091 8.00018L7.53732 3.46552L8.58962 4.53447Z" fill="currentColor"></path></svg>
          </view>
          <view style="cursor:pointer;margin-right: 20rpx;width: 40rpx" :style="{color: curIndex === historyDrawData.length - 1 ? '#999' : '#007aff'}" @click="redo">
            <svg role="img" aria-label="redo" focusable="false" data-icon="redo" aria-hidden="true" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="gd_design_icon gd_design_icon-redo"><path d="M15.4103 4.53445L18.1692 7.25078L9.49962 7.25078C6.04806 7.25078 3.25002 10.0488 3.25 13.5004C3.24999 16.9519 6.04804 19.75 9.49962 19.75H15V18.25H9.49962C6.87647 18.25 4.74999 16.1235 4.75 13.5004C4.75001 10.8772 6.87649 8.75078 9.49962 8.75078L18.1692 8.75078L15.4103 11.4671L16.4627 12.536L21.069 8.00078L16.4627 3.46558L15.4103 4.53445Z" fill="currentColor"></path></svg></view>
          <view style="cursor:pointer;">
            <view class="history-btn" @click="showHistoryWindow = !showHistoryWindow">历史</view>
            <view class="history-window" v-show="showHistoryWindow">
              <view class="history-top">
                <view>历史记录</view>
                <view class="close" @click="showHistoryWindow = false"><el-icon><Close /></el-icon></view>
              </view>
              <view class="history-list" ref="historyWindow">
                <view class="history-item" :style="{color: index <= curIndex?'':'rgb(175 175 175)'}" v-for="(item,index) of historyDrawData" @click="historyTo(index)">
                  <view>{{index + 1}}</view>
                  <view class="name">{{item.name}}</view>
                </view>
              </view>
            </view>
          </view>
          <view class="align-box" :class="{disabled: currentNodeElements.length < 2}">
            <view class="align-btn" @click="alignOperate.top">
              <el-tooltip
                  class="box-item"
                  effect="dark"
                  content="顶对齐"
                  placement="bottom"
              >
                <view><i class="iconfont icon-dingduiqi"></i></view>
              </el-tooltip>
            </view>
            <view class="align-btn" @click="alignOperate.verticalCenter()">
              <el-tooltip
                  class="box-item"
                  effect="dark"
                  content="垂直对齐"
                  placement="bottom"
              >
                <view><i class="iconfont icon-chuizhiduiqi"></i></view>
              </el-tooltip>
            </view>
            <view class="align-btn" @click="alignOperate.bottom()">
              <el-tooltip
                  class="box-item"
                  effect="dark"
                  content="底对齐"
                  placement="bottom"
              >
                <view><i class="iconfont icon-diduiqi"></i></view>
              </el-tooltip>
            </view>
            <view class="align-btn" @click="alignOperate.left()">
              <view class="align-btn">
                <el-tooltip
                    class="box-item"
                    effect="dark"
                    content="左对齐"
                    placement="bottom"
                >
                  <view><i class="iconfont icon-zuoduiqi"></i></view>
                </el-tooltip>
              </view>
            </view>
            <view class="align-btn" @click="alignOperate.horizontalCenter()">
              <el-tooltip
                  class="box-item"
                  effect="dark"
                  content="居中对齐"
                  placement="bottom"
              >
                <view><i class="iconfont icon-juzhongduiqi"></i></view>
              </el-tooltip>
            </view>
            <view class="align-btn" @click="alignOperate.right()">
              <el-tooltip
                  class="box-item"
                  effect="dark"
                  content="右对齐"
                  placement="bottom"
              >
                <view><i class="iconfont icon-youduiqi"></i></view>
              </el-tooltip>
            </view>
          </view>
        </view>
        <view class="top-btn" @click="importData">导入数据</view>
        <view class="top-btn" @click="exportData">导出数据</view>
        <view class="top-btn" @click="clearAll">清空所有元素</view>
      </view>

    </view>
    <view class="ep-wrapper">
      <view class="edit-wrapper">
        <view class="left-menu">
          <view class="left-view">
            <view class="left-menu-box" :class="{active:leftOpenActive === 'add'}" @click="leftOpenHand('add')">
              <el-icon class="icon"><CirclePlus /></el-icon>
              <view class="left-menu-name">添加</view>
            </view>
            <view class="left-menu-box" :class="{active:leftOpenActive === 'allComponent'}" @click="leftOpenHand('allComponent')">
              <el-icon class="icon"><Document /></el-icon>
              <view class="left-menu-name">组件</view>
            </view>
            <view class="left-menu-box" :class="{active:leftOpenActive === 'fonts'}" @click="leftOpenHand('fonts')">
              <el-icon class="icon"><Tickets /></el-icon>
              <view class="left-menu-name">字体</view>
            </view>
            <view class="left-menu-box" :class="{active:leftOpenActive === 'code'}" @click="leftOpenHand('code')">
              <el-icon class="icon"><Tickets /></el-icon>
              <view class="left-menu-name">代码</view>
            </view>
          </view>
          <view class="leftMenuActive" :class="{open:leftOpen}">
            <view class="component-list" v-show="leftOpenActive === 'add'">
              <view class="add-item add-text" @click="addNode('text',{text:'文字'})">
                文字
              </view>
              <view class="add-item add-image" @click="addNode('image',{url:'https://v-portrait.soqicn.com/e11a9237e3f9437d8e71b648f4cdc0c5.jpg-img120?t=20171220'})">
                图片
              </view>
              <view class="add-item icons" >
                <view>图标</view>
                <view class="add-icons">
                  <view @click="addNode('icon',{d:'M574.234,488.799c-11.133,0-20.099,9.585-20.099,21.643\n'+
'\tc0,12.06,8.966,21.645,20.099,21.645c11.131,0,20.097-9.585,20.097-21.645C594.331,498.385,585.365,488.799,574.234,488.799z\n'+
'\t M672.562,488.799c-11.131,0-20.099,9.585-20.099,21.643c0,12.06,8.968,21.645,20.099,21.645c11.131,0,20.097-9.585,20.097-21.645\n'+
'\tC692.659,498.385,683.693,488.799,672.562,488.799z M672.562,488.799c-11.131,0-20.099,9.585-20.099,21.643\n'+
'\tc0,12.06,8.968,21.645,20.099,21.645c11.131,0,20.097-9.585,20.097-21.645C692.659,498.385,683.693,488.799,672.562,488.799z\n'+
'\t M574.234,488.799c-11.133,0-20.099,9.585-20.099,21.643c0,12.06,8.966,21.645,20.099,21.645c11.131,0,20.097-9.585,20.097-21.645\n'+
'\tC594.331,498.385,585.365,488.799,574.234,488.799z M515.484,47.251c-241.491,0-437.527,195.419-437.527,436.6\n'+
'\ts196.036,436.909,437.527,436.909s437.529-195.728,437.529-436.909S756.974,47.251,515.484,47.251z M452.716,599.804\n'+
'\tc-25.046,0-48.546-4.329-69.881-12.06c-5.875,2.784-47.927,42.363-57.204,35.869c-6.492-5.875,14.843-48.855,16.698-56.276\n'+
'\tc-44.835-29.992-74.21-78.228-74.21-132.34c0-91.216,82.867-165.117,184.598-165.117c95.544,0,174.391,64.625,183.669,147.8\n'+
'\tc-4.02-0.617-8.349-0.617-12.679-0.617c-84.103,0-152.748,60.913-152.748,136.359c0,16.079,3.093,30.921,8.349,44.526\n'+
'\tC470.648,599.187,461.682,599.804,452.716,599.804z M706.883,654.843c1.236,5.875,17.625,38.341,12.679,42.671\n'+
'\tc-7.113,5.256-38.96-24.738-43.599-27.21c-15.77,5.875-34.012,9.276-52.875,9.276c-76.992,0-139.76-55.966-139.76-125.228\n'+
'\tc0-68.954,62.768-125.228,139.76-125.228c76.994,0,139.762,56.274,139.762,125.228C762.849,595.474,740.587,632.27,706.883,654.843z\n'+
'\t M672.562,488.799c-11.131,0-20.099,9.585-20.099,21.643c0,12.06,8.968,21.645,20.099,21.645c11.131,0,20.097-9.585,20.097-21.645\n'+
'\tC692.659,498.385,683.693,488.799,672.562,488.799z M574.234,488.799c-11.133,0-20.099,9.585-20.099,21.643\n'+
'\tc0,12.06,8.966,21.645,20.099,21.645c11.131,0,20.097-9.585,20.097-21.645C594.331,498.385,585.365,488.799,574.234,488.799z\n'+
'\t M517.339,405.004c15.151,0,26.901-12.986,26.591-28.756c0-16.079-12.058-29.066-26.591-29.066\n'+
'\tc-14.841,0-26.901,12.986-26.901,29.066C490.438,392.018,502.498,405.004,517.339,405.004z M387.781,347.182\n'+
'\tc-14.841,0-26.591,12.986-26.591,29.066c0,15.77,11.75,28.756,26.591,28.756c14.534,0,26.591-12.986,26.591-28.756\n'+
'\tC414.373,360.168,402.315,347.182,387.781,347.182z'})">微信</view>
                  <view @click="addNode('icon',{d:'M515.485,47.097c-241.49,0-437.528,195.728-437.528,436.909\n'+
'\ts196.038,436.909,437.528,436.909s437.528-195.728,437.528-436.909S756.975,47.097,515.485,47.097z M712.14,644.484\n'+
'\tc-8.657,29.065-46.998,72.353-81.631,72.353h-2.472c-52.875-2.782-124.611-55.347-191.708-140.688l-24.736-31.54\n'+
'\tc-66.79-85.339-102.038-168.825-93.69-222.936c5.565-38.341,59.677-70.5,90.597-70.5c15.153,0,20.718,7.73,22.573,12.679\n'+
'\tc17.315,32.776,38.96,89.669,39.268,110.077v1.236l-0.617,1.546c-3.71,10.514-12.369,15.77-20.099,20.409\n'+
'\tc-9.895,5.875-15.77,9.895-16.387,21.026c-0.31,3.401,2.472,19.171,46.689,76.373l18.863,24.119\n'+
'\tc44.526,55.038,58.439,61.222,61.532,61.532c10.821,1.546,15.77-3.401,23.5-12.369c5.875-6.492,12.367-14.222,23.498-16.077h1.238\n'+
'\tl1.546,0.31c19.171,4.327,68.645,37.722,96.782,62.768C710.903,617.583,718.015,625.93,712.14,644.484z'})">电话</view>
                  <view @click="addNode('icon',{d:'M515.485,47.097c-241.49,0-437.528,195.728-437.528,436.909\n'+
'\ts196.038,436.909,437.528,436.909s437.528-195.728,437.528-436.909S756.975,47.097,515.485,47.097z M531.564,723.331\n'+
'\tc-9.278,9.276-22.881,9.276-32.159,0c-59.367-59.677-169.444-166.044-169.444-287.871c0-109.151,82.867-197.583,185.214-197.583\n'+
'\tS701.009,326.31,701.009,435.46C701.009,556.669,588.767,664.891,531.564,723.331z M515.175,361.559\n'+
'\tc-38.341,0-69.881,32.466-69.881,73.901c0,41.742,31.54,74.827,69.881,74.827c38.341,0,69.881-32.466,69.881-73.901\n'+
'\tC585.056,394.645,553.517,361.559,515.175,361.559z'})">导航</view>
                </view>
              </view>
            </view>
            <view class="allComponent" v-show="leftOpenActive === 'allComponent'">
              <view style="display: flex;align-items: center;justify-content: space-between;padding: 10rpx">
                <view style="padding: 10rpx">组件列表：</view>
                <view style="cursor:pointer;" @click="importData">导入数据</view>
              </view>
              <view class="all-component-list" tabindex="0" @keydown="keyDown" @keyup="keyUp">
                <template v-if="drawData.nodeElements.length > 0">
                  <draggable :list="drawData.nodeElements"
                             :force-fallback="true"
                             chosen-class="chosen"
                             :handle="`.mover`"
                             item-key="id"
                             @end="saveHistory('拖动排序')"
                             animation="300">
                    <template #item="{ element: item }">
                      <view class="component-item" >
                        <view v-if="item.resourceType != 'group'" class="data" :class="{selected: isSelected(item)}"  @click="componentItemClick(item)">
                          <view class="data-content">
                            <view>
                              组件名称：<input class="component-name" :value="item.name?item.name:''" placeholder="未命名" @update:modelValue="showNodeItemUpdate"/>
                            </view>
                            <view>组件类型：{{item.resourceType}}</view>
                          </view>
                          <view>
                            <view class="mover">
                              <svg class="icon" style="width: 1.0283203125em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1053 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4748"><path d="M737.865143 211.236571L526.628571 0l-211.236571 211.236571h422.473143zM737.865143 812.763429L526.628571 1024l-211.236571-211.236571h422.473143z" fill="#969696" p-id="4749"></path><path d="M0 349.330286m58.514286 0l936.228571 0q58.514286 0 58.514286 58.514285l0 0q0 58.514286-58.514286 58.514286l-936.228571 0q-58.514286 0-58.514286-58.514286l0 0q0-58.514286 58.514286-58.514285Z" fill="#969696" p-id="4750"></path><path d="M0 572.269714m58.514286 0l936.228571 0q58.514286 0 58.514286 58.514286l0 0q0 58.514286-58.514286 58.514286l-936.228571 0q-58.514286 0-58.514286-58.514286l0 0q0-58.514286 58.514286-58.514286Z" fill="#969696" p-id="4751"></path></svg>
                            </view>
                          </view>

                        </view>
                        <view v-else class="group" @click="componentGroupItemClick(item)">
                          <view class="group-content" :class="{selected: isSelectedGroup(item)}">
                            <view>
                              <view>
                                组件名称：<input class="component-name" :value="item.name?item.name:''" placeholder="未命名" @update:modelValue="showNodeItemUpdate"/>
                              </view>
                              <view>组件类型：文件夹</view>
                            </view>

                            <view class="mover">
                              <svg class="icon" style="width: 1.0283203125em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1053 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4748"><path d="M737.865143 211.236571L526.628571 0l-211.236571 211.236571h422.473143zM737.865143 812.763429L526.628571 1024l-211.236571-211.236571h422.473143z" fill="#969696" p-id="4749"></path><path d="M0 349.330286m58.514286 0l936.228571 0q58.514286 0 58.514286 58.514285l0 0q0 58.514286-58.514286 58.514286l-936.228571 0q-58.514286 0-58.514286-58.514286l0 0q0-58.514286 58.514286-58.514285Z" fill="#969696" p-id="4750"></path><path d="M0 572.269714m58.514286 0l936.228571 0q58.514286 0 58.514286 58.514286l0 0q0 58.514286-58.514286 58.514286l-936.228571 0q-58.514286 0-58.514286-58.514286l0 0q0-58.514286 58.514286-58.514286Z" fill="#969696" p-id="4751"></path></svg>
                            </view>
                          </view>
                          <view class="group-data">
                            <draggable :list="item.children"
                                       :force-fallback="true"
                                       chosen-class="chosen"
                                       :handle="`.mover`"
                                       item-key="id"
                                       @end="saveHistory('拖动排序')"
                                       animation="300">
                              <template #item="{ element: child }">
                                <view class="data" @click.stop="componentItemClick(child)" :class="{selected: isSelected(child)}">
                                  <view>
                                    <view>{{child.name}}</view>
                                    <view>{{child.resourceType}}</view>
                                  </view>
                                  <view class="mover">
                                    <svg class="icon" style="width: 1.0283203125em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1053 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4748"><path d="M737.865143 211.236571L526.628571 0l-211.236571 211.236571h422.473143zM737.865143 812.763429L526.628571 1024l-211.236571-211.236571h422.473143z" fill="#969696" p-id="4749"></path><path d="M0 349.330286m58.514286 0l936.228571 0q58.514286 0 58.514286 58.514285l0 0q0 58.514286-58.514286 58.514286l-936.228571 0q-58.514286 0-58.514286-58.514286l0 0q0-58.514286 58.514286-58.514285Z" fill="#969696" p-id="4750"></path><path d="M0 572.269714m58.514286 0l936.228571 0q58.514286 0 58.514286 58.514286l0 0q0 58.514286-58.514286 58.514286l-936.228571 0q-58.514286 0-58.514286-58.514286l0 0q0-58.514286 58.514286-58.514286Z" fill="#969696" p-id="4751"></path></svg>
                                  </view>
                                </view>
                              </template>
                            </draggable>

                          </view>
                        </view>

                      </view>


                    </template>

                  </draggable>

                </template>

              </view>
            </view>
            <view class="fonts-box" v-show="leftOpenActive === 'fonts'">
              <el-card class="box-card" :body-style="{
                  display: 'flex',
                  flexDirection: 'column',
                  flex: 1,
                  overflow: 'auto'
                }">
                <template #header>
                  <view class="card-header">
                    <span>字体库:</span>
                    <el-button class="button" text @click="addFont(drawData.faces)">添加字体库</el-button>
                  </view>
                </template>
                <view class="fonts-list" v-if="drawData.faces.length > 0">
                  <view class="fonts-item" v-for="(item,index) in drawData.faces" :key="index">
                    <view class="font-top">
                      <view style="font-size: 50rpx">字体{{index + 1}}</view>
                      <el-popconfirm title="确定删除么?" confirm-button-text="确定" cancel-button-text="取消" @confirm="deleteFont(drawData.faces,item,index)">
                        <template #reference>
                          <view class="font-delete" @click="()=>{if(!item.name && !item.url){deleteFont(drawData.faces,item,index)}}">
                            <el-icon><Minus /></el-icon>
                          </view>
                        </template>
                      </el-popconfirm>

                    </view>
                    <view class="font-content">
                      <view class="font-name">
                        <view>名称：</view><input class="component-name" v-model="item.name"/>
                      </view>
                      <view class="font-url">
                        <view>路径：</view><input class="component-name" v-model="item.url"/>
                      </view>
                    </view>
                  </view>
                </view>
              </el-card>
            </view>
            <view class="code" v-show="leftOpenActive === 'code'">
              <CodeEdit :code="drawData.beforeCode" @save="(code)=>{drawData.beforeCode = code}"></CodeEdit>
            </view>
            <view v-if="leftOpen" @click="leftOpenActive = ''" class="shrink"></view>
          </view>
        </view>
        <view class="edit-content">

          <view class="edit-content-component" tabindex="0" @click.right.stop="rightClick" @mousemove="move" :class="{pointer: isSpace}" @click="pageClick">
            <view v-if="drawData" class="canvas-box"
                  :style="{width: drawData.width * showScale/100 + 'px', height: drawData.height * showScale/100 + 'px', transform: `translate(${boxMoveXy.x}px,${boxMoveXy.y}px)`}"
                  tabindex="0">
              <HadaCanvasPosterH5 ref="hadaCanvas" :draw-data="drawData" @change="change" @drawError="drawError"></HadaCanvasPosterH5>

            </view>
            <view style="box-sizing: border-box;" >
              <template v-if="moveNodes.length > 0">
                <view class="content-component editor-transform move-node" style="position: absolute" :style="getCurrentNodeElementStyle(moveNodes[0])">
                </view>
              </template>
              <view tabindex="-1" ref="keyDownLeftTopRef" @keydown="keyDownLeftTop" >
                <template v-if="currentNodeElements.length > 0">
                  <view class="content-component editor-transform" style="position: absolute" v-for="(item, index) in currentNodeElements" :style="getCurrentNodeElementStyle(item)">
                    <template v-if="moveAndNode">
                      <template v-if="item.resourceType === 'text'">
                        <text :style="getCurrentNodeElementImageStyle(item)">{{item.text}}</text>
                      </template>
                      <template v-if="item.resourceType === 'image'">
                        <image :style="getCurrentNodeElementImageStyle(item)" :src="item.url" style="width: 100%;height: 100%;"></image>
                      </template>
                    </template>
                    <template v-if="item.css.width > 0 && item.css.height > 0">
                      <i @mousedown="editorDown($event,0,item)" data-cursor="nsResize" class="editor-grip editor-grip-s editor-transition" style="padding: 8px;"><b style="width: 14px;"></b></i>
                      <template v-if="!item.css.dynamicLocation">
                        <i @mousedown="editorDown($event,1,item)" data-cursor="neswResize" class="editor-grip editor-grip-sw editor-transition" style="padding: 8px;"><b></b></i>
                        <i @mousedown="editorDown($event,2,item)" data-cursor="ewResize" class="editor-grip editor-grip-w editor-transition" style="padding: 8px;"><b style="height: 14px;"></b></i>
                        <i @mousedown="editorDown($event,3,item)" data-cursor="nwseResize" class="editor-grip editor-grip-nw editor-transition" style="padding: 8px;"><b></b></i>
                        <i @mousedown="editorDown($event,4,item)" data-cursor="nsResize" class="editor-grip editor-grip-n editor-transition" style="padding: 8px;"><b style="width: 14px;"></b></i>
                        <i @mousedown="editorDown($event,5,item)" data-cursor="neswResize" class="editor-grip editor-grip-ne editor-transition" style="padding: 8px;"><b></b></i>
                      </template>
                      <i @mousedown="editorDown($event,6,item)" data-cursor="ewResize" class="editor-grip editor-grip-e editor-transition" style="padding: 8px;"><b style="height: 14px;"></b></i>
                      <i @mousedown="editorDown($event,7,item)" data-cursor="nwseResize" class="editor-grip editor-grip-se editor-transition" style="padding: 8px;"><b></b>
                      </i>
                      <div class="editor-mouse-tips" style="left: 0px; top: 0px;transform: translate(5px,5px)" :style="{left:item.css.width * showScale/100+'px',top: item.css.height* showScale/100 + 'px'}"
                           v-show="editor.cursor < 8 && editor.cursor > 0">{{item.css.width}} x {{item.css.height}}</div>
                    </template>
                    <i @mousedown="editorDown($event,8,item)" data-cursor="cursor:rotator, rotate:0" class="editor-rotator editor-transition"
                       style="margin-top: 14px;">
                      <b :style="{transform: `rotate(${-item.css.angle}deg)`}">
                        <span v-show="editor.cursor === 8">{{item.css.angle}}°</span></b>
                    </i>
                  </view>
                  <view v-show="alignLineNodes[0].length > 0" class="v-line left-line" style="position: absolute" :style="getLeftLine(currentNodeElements[0])"></view>
                  <view v-show="alignLineNodes[1].length > 0" class="v-line v-middle-line" style="position: absolute" :style="getMiddleLine(currentNodeElements[0])"></view>
                  <view v-show="alignLineNodes[2].length > 0" class="v-line right-line" style="position: absolute" :style="getRightLine(currentNodeElements[0])"></view>
                  <view v-show="alignLineNodes[3].length > 0" class="h-line top-line" style="position: absolute" :style="getTopLine(currentNodeElements[0])"></view>
                  <view v-show="alignLineNodes[4].length > 0" class="h-line h-middle-line" style="position: absolute" :style="getHMiddleLine(currentNodeElements[0])"></view>
                  <view v-show="alignLineNodes[5].length > 0" class="h-line bottom-line" style="position: absolute" :style="getBottomLine(currentNodeElements[0])"></view>
                </template>
              </view>

              <template  v-for="(items, i) in alignLineNodes">
                <template v-for="(item, j) in items">
                  <view v-if="item != null" class="content-component align-line" style="position: absolute" :style="getCurrentNodeElementStyle(item)">
                  </view>
                </template>
              </template>
            </view>
            <view class="ruler-wrapper">
              <view class="ruler-x"></view>
              <view class="ruler-y"></view>

              <view v-for="line in rulerLines.filter(item=>item.type === 'x')" class="ruler-line" :class="`ruler-line-${line.type}`" :style="{top:line.v * showScale/100 + boxMoveXy.y+'px'}" @mousedown="ruler.lineMousedown($event,line)" @mouseover="ruler.lineMouseOver($event,line)" @mouseout="line.showTip = false">
                <view v-show="line.showTip" :style="{transform: `translateX(${line.move + 20}px)`}">
                  <view class="show-tip" v-if="line.isRetain">Y:{{line.v}}px</view>
                  <view class="show-tip" v-else>放开移除</view>
                </view>
              </view>

              <view v-for="line in rulerLines.filter(item=>item.type === 'y')" class="ruler-line" :class="`ruler-line-${line.type}`" :style="{left:line.v * showScale/100 + boxMoveXy.x+'px'}" @mousedown="ruler.lineMousedown($event,line)" @mouseover="ruler.lineMouseOver($event,line)" @mouseout="line.showTip = false">
                <view v-show="line.showTip" :style="{transform: `translateY(${line.move + 20}px)`}">
                  <view class="show-tip" v-if="line.isRetain">X:{{line.v}}px</view>
                  <view class="show-tip" v-else>放开移除</view>
                </view>
              </view>

            </view>
          </view>
        </view>
        <view class="component-props" :class="{open:componentPropsShow}" >
          <view style="position: sticky;top:0;z-index: 1">
<!--            <HadaCanvasPoster2d :draw-data="drawData"></HadaCanvasPoster2d>-->
          </view>

          <view style="display: flex;flex-direction: column">

            <view>组件属性</view>

            <view v-for="(node,index) in currentNodeElements" >
              <view style="border-bottom: #00000055 dashed 1px;padding: 10rpx"></view>

              <view class="props" v-if="node">
                <view class="prop-item">
                  <text class="prop-name">组件名称</text>
                  <input type="text" v-model="node.name" placeholder="请输入组件名称">
                  <view style="display: flex">
                    <view style="cursor:pointer;color:#007aff;margin-right: 10rpx" @click="copyNode(node,index)">复制</view>
                    <view style="cursor:pointer;color: red;" @click="deleteNode(node,index)">删除</view>
                  </view>
                </view>
                <view class="prop-item"><text class="prop-name">组件类型</text><input type="text" :value="node.resourceType" readonly></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">文字内容</text><input maxlength="-1" @confirm="saveHistory('修改文字内容')" type="text" v-model="node.text"></view>
                <view class="prop-item" v-if="node.resourceType === 'image'">
                  <text class="prop-name">图片地址</text>
                  <input maxlength="-1" @confirm="saveHistory('修改图片地址')" type="text" v-model="node.url">
                </view>
                <view class="prop-item" v-if="node.resourceType === 'image'">
                  <text class="prop-name">蒙版地址</text>
                  <input maxlength="-1" @confirm="saveHistory('修改蒙版地址')" type="text" v-model="node.css.maskImage">
                </view>
                <view class="prop-item" v-if="node.resourceType === 'image'">
                  <text class="prop-name">图片模式</text>
                  <el-select v-model="node.css.mode" filterable @change="saveHistory('修改图片模式')" placeholder="scaleToFill">
                    <el-option
                        v-for="item in modes"
                        :key="item"
                        :label="item"
                        :value="item"
                    />
                  </el-select>
                  <el-select clearable v-model="node.css.mirrorImage" filterable @change="saveHistory('修改图片模式')" placeholder="镜像">
                    <el-option
                        v-for="item in ['horizontal', 'vertical']"
                        :key="item"
                        :label="item"
                        :value="item"
                    />
                  </el-select>
<!--                  <input maxlength="-1" @confirm="saveHistory" type="text" v-model="node.css.mode">-->
                </view>
                <view class="prop-item" v-if="node.resourceType === 'icon'"><text class="prop-name">图标d值</text><input maxlength="-1" @confirm="saveHistory('修改图标d值')" type="text" v-model="node.d"></view>
                <view class="prop-item"><text class="prop-name">type(自定义字段)</text>
                  <input type="number" :value="node.type" @update:modelValue="node.type = +$event" placeholder="自定义字段(数字类型)"></view>
                <template v-if="!node.css.dynamicLocation">
                  <view class="prop-item"><text class="prop-name">left</text><input @confirm="saveHistory('调整left')" type="number" :value="node.css.left" @update:modelValue="node.css.left = +$event"></view>
                  <view class="prop-item"><text class="prop-name">top</text><input @confirm="saveHistory('调整top')" type="number" :value="node.css.top" @update:modelValue="node.css.top = +$event"></view>
                </template>

                <view class="prop-item dynamicLocation">
                  <text class="prop-name">动态位置</text>

                  <view style="display: flex;flex-direction: column;flex: 1;">
                    <view style="display: flex;justify-content: space-between;flex: 1;">
                      <view v-if="node.css.dynamicLocation" style="margin-top: 5px;">
                        相对上一个元素的位置
                      </view>
                      <view>
                        <el-switch :value="!!node.css.dynamicLocation" @update:modelValue="dynamicLocationSwitch(node,draw)"/>
                      </view>
                    </view>
                    <view v-if="node.css.dynamicLocation">
                      <view style="margin-bottom: 10rpx">
                        <text>方 向 ：</text>
                        <el-select style="width: 200rpx" v-model="node.css.dynamicLocation.direction" filterable @change="saveHistory('调整方向')" placeholder="right">
                          <el-option
                              v-for="item in ['left', 'right', 'top', 'bottom']"
                              :key="item"
                              :label="item"
                              :value="item"
                          />
                        </el-select>
                      </view>
                      <view style="margin-bottom: 10rpx">
                        <text>top偏移 ：</text><el-input-number @change="saveHistory('调整top偏移')" v-model="node.css.dynamicLocation.offset.top" :controls="false" placeholder="0"></el-input-number>
                      </view>
                      <view>
                        <text>left偏移 ：</text><el-input-number @change="saveHistory('调整left偏移')" v-model="node.css.dynamicLocation.offset.left"  :controls="false" placeholder="0"></el-input-number>
                      </view>


                    </view>
                  </view>
                </view>


                <view class="prop-item"><text class="prop-name">透明度</text>
<!--                  <el-input-number @change="saveHistory('修改透明度')" v-model="node.css.opacity" :min="0" :max="1" :precision="2" :controls="false" placeholder="1" style="width: 130rpx"></el-input-number>-->
                  <view>
                    <HadaProgress @confirm="saveHistory('修改透明度')" :modelValue="Math.round((node.css.opacity??1)*100)" @update:modelValue="v => node.css.opacity = v/100"></HadaProgress>
                  </view>
                </view>

<!--                <view class="prop-item"><text class="prop-name">属性计算函数</text>
                  <view style="display: flex;flex-direction: column">
                    <view style="font-size: 14px">function(node,propName,nodes){</view>
                    <el-input type="textarea" :rows="15" v-model="calcProp" @change="calcProperyUpdate(node,$event)"></el-input>
                    <view style="font-size: 14px">}</view>
                  </view>
                </view>-->

                <view class="prop-item"><text class="prop-name">宽度</text><input @confirm="saveHistory('调整宽度')" type="number" :value="node.css.width" @update:modelValue="node.css.width = +$event"></view>

                <view class="prop-item" v-if="node.resourceType === 'text' && node.css.width === 0"><text class="prop-name">最大宽度</text><input @confirm="saveHistory('修改最大宽度')" type="number" :value="node.css.maxWidth" @update:modelValue="node.css.maxWidth = +$event" placeholder="设置大于0的值可启用"></view>

                <view class="prop-item"><text class="prop-name">高度</text><input @confirm="saveHistory('修改高度')" type="number" :value="node.css.height" @update:modelValue="node.css.height = +$event"></view>
                <view class="prop-item"><text class="prop-name">层级</text><input @confirm="saveHistory('修改层级')" type="number" :value="node.css.zIndex" @update:modelValue="node.css.zIndex = +$event" placeholder="0"></view>
                <view class="prop-item">
                  <text class="prop-name">背景颜色</text>
                  <view class="background-color">
                    <view class="background-color-content" v-if="!Array.isArray(node.css.backgroundColor)">
                      <view>{{node.css.backgroundColor}}</view>
                      <el-color-picker @change="saveHistory('修改背景颜色')" v-model="node.css.backgroundColor" show-alpha/>
                    </view>
                    <view class="background-color-content" v-else>
                      <view class="backgroundColorGradientDirection">
                        <view style="width: 100rpx">方向：</view>
                        <el-select v-model="node.css.backgroundColorGradientDirection" @change="saveHistory('修改背景颜色')" placeholder="Select" style="width: 250rpx">
                          <el-option
                              v-for="item in ['to bottom', 'to top' , 'to left' ,'to right']"
                              :key="item"
                              :label="item"
                              :value="item"
                          />
                        </el-select>
                      </view>
                      <view>
                        <el-color-picker v-for="(item,index) in node.css.backgroundColor" @change="saveHistory('修改背景颜色')" v-model="node.css.backgroundColor[index]" show-alpha/>
                        <view class="background-color-gradient-add" @click="addBackgroundColor(node)">添加</view>
                      </view>

                    </view>
                    <view class="backgroundColorGradient">
                      <el-checkbox :model-value="Array.isArray(node.css.backgroundColor)"  @change="enableGradient($event,node)" label="渐变" size="large" />
                      <view class="background-color-gradient-delete" v-if="Array.isArray(node.css.backgroundColor)" @click="removeColor(node)">删除</view>
                    </view>
                  </view>
                </view>

                <view class="prop-item" v-if="node.resourceType === 'icon'"><text class="prop-name">图标颜色</text>
                  <view>{{node.css.color}}</view><el-color-picker @change="saveHistory('修改图标颜色')" v-model="node.css.color" show-alpha/>
                </view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">文字颜色</text>
                  <view>{{node.css.color}}</view><el-color-picker @change="saveHistory('修改文字颜色')" v-model="node.css.color" show-alpha/>
                </view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">文字字体</text><input @confirm="saveHistory('修改文字字体')" type="text" v-model="node.css.font" placeholder="即将废弃 使用字体大小 字体列表"></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">字体大小</text><input @confirm="saveHistory('修改字体大小')" type="text" v-model="node.css.fontSize" placeholder="32"></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">字体列表</text><input @confirm="saveHistory('修改字体列表')" type="text" v-model="node.css.fontFamily" placeholder="SimHei"></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">行间距</text><input @confirm="saveHistory('修改行间距')" type="number" :value="node.css.lineSpacing" @update:modelValue="node.css.lineSpacing = +$event" placeholder="0"></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">文字最大行</text><input @confirm="saveHistory('修改文字最大行')" type="text" v-model="node.css.maxLine" placeholder="1"></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">超出替换字符</text><input @confirm="saveHistory('修改超出替换字符')" type="text" v-model="node.css.textOverflow"></view>
                <view class="prop-item" v-if="node.resourceType === 'text'"><text class="prop-name">文字对齐</text><input @confirm="saveHistory('修改文字对齐')" type="text" v-model="node.css.textAlign" placeholder="left"></view>

                <view class="prop-item">
                  <text class="prop-name">边框颜色</text>
                  <view>{{node.css.borderColor}}</view><el-color-picker @change="saveHistory('修改边框颜色')" v-model="node.css.borderColor" show-alpha/>
                </view>
                <view class="prop-item"><text class="prop-name">边框宽度</text><input @confirm="saveHistory('修改边框宽度')" type="number" :value="node.css.borderWidth" @update:modelValue="node.css.borderWidth = +$event" placeholder="0"></view>
                <view class="prop-item"><text class="prop-name">圆角</text><input @confirm="saveHistory('修改圆角')" type="number" :value="node.css.borderRadius" @update:modelValue="node.css.borderRadius = +$event" placeholder="0"></view>
                <view class="prop-item" v-if="node.resourceType === 'image'">
                  <text class="prop-name">路径形状</text><input maxlength="-1" @confirm="saveHistory('修改路径形状')" type="text" v-model="node.css.clipPath"></view>

                <view class="prop-item"><text class="prop-name">旋转角度</text><input @confirm="saveHistory('修改旋转角度')" type="number" :value="node.css.angle" @update:modelValue="node.css.angle = +$event" placeholder="0"></view>


                <view class="prop-item">
                  <text class="prop-name">阴影颜色</text>
                  <view>{{node.css.shadowColor}}</view><el-color-picker @change="saveHistory('修改阴影颜色')" v-model="node.css.shadowColor" show-alpha/>
                </view>
                <view class="prop-item"><text class="prop-name">阴影大小</text><input @confirm="saveHistory('修改阴影大小')" type="number" :value="node.css.shadowBlur" @update:modelValue="node.css.shadowBlur = +$event" placeholder="0"></view>
                <view class="prop-item"><text class="prop-name">阴影偏移X</text><input @confirm="saveHistory('修改阴影偏移X')" type="number" :value="node.css.shadowOffsetX" @update:modelValue="node.css.shadowOffsetX = +$event" placeholder="0"></view>
                <view class="prop-item"><text class="prop-name">阴影偏移Y</text><input @confirm="saveHistory('修改阴影偏移Y')" type="number" :value="node.css.shadowOffsetY" @update:modelValue="node.css.shadowOffsetY = +$event" placeholder="0"></view>

              </view>
            </view>
          </view>
          <view>
            操作说明:
            <view>
              <view>1、空格+鼠标左键 可拖动</view>
              <view>2、Alt+滚轮 放大缩小</view>
              <view>3、Ctrl+鼠标左键 多选组件</view>
              <view>4、组件列表点击可以快速选中组件</view>
              <view>5、Ctrl+Z 撤销，Ctrl+Shift+Z 重做</view>
            </view>

          </view>
        </view>
      </view>
    </view>

  </view>


</template>

<script setup lang="ts">
import {DrawData, NodeElement} from "./components/hada-canvas-poster/types";
import HadaCanvasPosterH5 from "./components/hada-canvas-poster/HadaCanvasPosterH5.vue";

import {nextTick, onMounted, reactive, ref, watchEffect} from "vue";
import {templateDatas} from './templateDatas'

import {alignLineNodes, alignLineRun} from "./align-line";
import {openPsd} from "../../utils/psdParse";
import {
  addFont, deleteFont,
  leftOpen,
  leftOpenActive,
  leftOpenHand,
  showTemplates
} from "./menuHandle";
import {dynamicLocationSwitch, modes} from "./propInput";
import {View} from "@element-plus/icons-vue";
import draggable from 'vuedraggable'
import {ElMessage, ElMessageBox} from "element-plus";
import {openMenu} from "./ContextMenuMange";
import {
  actualMultiple, boxMoveXy,
  curIndex,
  currentNodeElements,
  drawData,
  historyDrawData, rulerLines,
  setHadaCanvas, setHistoryWindow, showHistoryWindow,
  showNodeElements, showScale
} from "./pageData";
import {
  addNode, alignOperate,
  clearAll, copyCurrentNodeElementsToStickup,
  copyNode,
  copyObj,
  deleteCurrentNodeElements, deleteNode,
  draw, historyTo,
  importData,
  redo,
  saveHistory, stickupData,
  undo
} from "./nodeElementOperation";
import Ruler from "./ruler";
import CodeEdit from "./components/codeEdit/codeEdit.vue";
import HadaCanvasPoster2d from "./components/hada-canvas-poster/HadaCanvasPoster2d.vue";
import HadaProgress from "../../components/cProgress/HadaProgress.vue";

let hadaCanvas = ref();
/**
 * 历史窗口
 */
let historyWindow = ref();

const showNodeItemUpdate = (e) => {
  currentNodeElements.value[0].name = e;
}

const componentItemClick = (item)=>{

  if(isControl.value){
    const index = currentNodeElements.value.indexOf(item);
    if(index === -1){
      currentNodeElements.value.push(item);
    }else {
      currentNodeElements.value.splice(index,1);
    }
  }else{
    currentNodeElements.value = [item];
  }

}
const componentGroupItemClick = (group : NodeElement)=>{

  if(isControl.value){
    group.children.forEach(item=>{
      const index = currentNodeElements.value.indexOf(item);
      if(index === -1){
        currentNodeElements.value.push(item);
      }else {
        currentNodeElements.value.splice(index,1);
      }
    })
  }else{

    currentNodeElements.value = [...group.children];
  }

}

function generateId() {
  return Math.random().toString(36).slice(2) + Date.now();
}
function nodeElementGenerateId() {
  function _run(node: NodeElement) {
    node.id = node.id || generateId();
    if (node.resourceType !== 'group') {
      return;
    }
    if (!node.children || node.children.length === 0) {
      return;
    }
    node.children.forEach((item)=>{
      _run(item);
    })
  }
  drawData.value.nodeElements.forEach((item)=>{
    _run(item);
  })

}

const selectedTemplate = (item)=>{
  showTemplates.value = false;
  drawData.value = item;
  nodeElementGenerateId();
  saveHistory();
}


const loadPsd = async () => {
  let dataPsd = await openPsd();
  drawData.value = dataPsd;
  nodeElementGenerateId();
  adaptiveShow();
  draw();
}

function adaptiveShow() {
  let editContentRect = document.querySelector('.edit-content').getBoundingClientRect();
  editWidth = editContentRect.width;
  editHeight = editContentRect.height;
  editContentWidth.value = editWidth + 'px';
  editContentHeight.value = editHeight + 'px';
  if(drawData.value.height > drawData.value.width) {
    const th = editContentRect.height/drawData.value.height;
    if(th > 1){
      showScaleInput.value = 100;
    }else{
      //预留百分之2 边框
      showScaleInput.value = Math.floor(th * 100 - 2);
    }
  } else {
    const wh = editContentRect.width/drawData.value.width;
    if(wh > 1){
      showScaleInput.value = 100;
    }else{
      //预留百分之2 边框
      showScaleInput.value = Math.floor(wh * 100 - 2);
    }
  }

  setCanvasSize();
  nextTick(()=>{
    setTimeout(()=>{
      let canvasBoxRect = document.querySelector('.canvas-box').getBoundingClientRect();
      boxMoveXy.value.x = (editContentRect.width - canvasBoxRect.width) / 2;
      boxMoveXy.value.y = (editContentRect.height - canvasBoxRect.height) / 2;
    },101)
  })

}


const showScaleInput = ref(showScale.value)


//鼠标左键点击
let leftMouseClick = false;
let startX = 0;
let startY = 0;
let startLeft = 0;
let startTop = 0;
//移动并有节点
let moveAndNode = false;

async function clickNodeRun(e) {
  if(isSpace.value){
    return;
  }
  if (editor.node) {
    return;
  }

  if(!hadaCanvas.value){
    return;
  }
  const x = e.clientX;
  const y = e.clientY;
  const nodes = await hadaCanvas.value.getNodeElementByPoint(x,y);
  componentClick(nodes);
}

const moveNodes = ref<NodeElement[]>([])
async function move(e) {
  if (editor.node) {
    return;
  }
  if (leftMouseClick){
    return;
  }
  if(!hadaCanvas.value){
    return;
  }
  if(ruler.value.leftClick){
    return;
  }
  const x = e.clientX;
  const y = e.clientY;
  const nodes = await hadaCanvas.value.getNodeElementByPoint(x,y);
  moveNodes.value = nodes;
}


const selectedUp = async (e) => {
  console.log('selectedUp',e)

  const moveX = e.clientX - startX;
  const moveY = e.clientY - startY;
  console.log('selectedUp',moveX,moveY)
  startX = 0;
  startY = 0;
  if(leftMouseClick){
    await clickNodeRun(e);
  }

  leftMouseClick = false;


  if(editor.node){
    saveHistory('拖动调整大小');
  }else{
    if(currentNodeElements.value.length > 0 && (Math.abs(moveX) > 0 || Math.abs(moveY) > 0)) {
      saveHistory('拖动节点');
    }
  }

  editor.left = 0;
  editor.top = 0;
  editor.angle = 0;
  editor.node = null;
  editor.width = 0;
  editor.height = 0;
  editor.leftMouseClick = false;
  editor.cursor = -1;
  alignLineNodes.value = [[],[],[],[],[],[]];
  moveAndNode = false
  draw();
}

const selectedDown=(e : MouseEvent)=>{
  if(ruler.value.leftClick){
    return;
  }

  console.log('selectedDown',e,e.button)
  leftMouseClick = e.button === 0;
  moveAndNode = false;
  startX = e.clientX;
  startY = e.clientY;

  if(editor.leftMouseClick){
    lastPointermove.x = editor.left + editor.width/2;
    lastPointermove.y = editor.top + editor.height + 25;
    origin.x = editor.left + editor.width/2;
    origin.y = editor.top + editor.height/2;
    lastPointermove = clacInitAnglePoint(editor.angle,lastPointermove,origin);
  }

  if(leftMouseClick){
    if(currentNodeElements.value.length > 0) {
      currentNodeElements.value.forEach(item=>{
        item.moveData = {left:item.css.left,top:item.css.top};
      })
      startLeft = currentNodeElements.value[0].css.left;
      startTop = currentNodeElements.value[0].css.top;
    }
    boxMoveXy.value.moveStartX =  boxMoveXy.value.x;
    boxMoveXy.value.moveStartY =  boxMoveXy.value.y;
  }
}


/**
 * 移动对齐线处理
 * @param moveX
 * @param moveY
 */
function editorMoveAlignLine(moveX: number, moveY: number) {
  alignLineRun(currentNodeElements.value,showNodeElements.value,drawData.value,moveX,moveY);
}


const selectedMove = (e: MouseEvent) => {

  const moveX = e.clientX - startX;
  const moveY = e.clientY - startY;

  if(leftMouseClick){


    //空格按键 移动画布
    if(isSpace.value){
      boxMoveXy.value.x = boxMoveXy.value.moveStartX + moveX;
      boxMoveXy.value.y = boxMoveXy.value.moveStartY + moveY;
      return;
    }

    //9点操作处理
    const isOver = editorMove({moveX,moveY});
    //元素拖动
    if(currentNodeElements.value.length > 0 && !editor.node){
      currentNodeElements.value.forEach(item=>{
        if(item.css.dynamicLocation){
          return;
        }
        item.css.left = item.moveData.left + moveX * actualMultiple.value;
        item.css.top = item.moveData.top + moveY * actualMultiple.value;
      })
      moveAndNode = true
    }

    editorMoveAlignLine(moveX,moveY);

    // draw();

  }
}

const pageClick = (e) => {
  console.log(e)
  // if(moveAndNode){
  //   return;
  // }
  // currentNodeElements.value = []
}


const isSpace = ref(false);//空格键
const isAlt = ref(false);//alt按键
const isControl = ref(false);//control按键
const isShift = ref(false);//shift按键


const keyDown = (e : KeyboardEvent) => {
  console.log('keyDown')

  switch (e.code) {
    case "Space":
      isSpace.value = true;
      e.preventDefault();
      break;
    case "AltLeft":
    case "AltRight":
      isAlt.value = true;
      e.preventDefault();
      break;
    case "ControlLeft":
    case "ControlRight":
      isControl.value = true;
      e.preventDefault();
      break;
    case "ShiftLeft":
    case "ShiftRight":
      isShift.value = true;
      e.preventDefault();
      break;
  }
}

const rightClick = (e: MouseEvent) => {
  console.log('rightClick',e)
  e.preventDefault();
  if(currentNodeElements.value.length > 0){
    openMenu(e);
  }
}

const keyDownLeftTop = (e)=>{
  console.log('keyDownLeftTop',e)
  const node = currentNodeElements.value[0];
  if(node.css.dynamicLocation){
    return;
  }
  switch (e.code) {
    case "ArrowLeft":
      if(!node) return;
      currentNodeElements.value.forEach(item=>{
        item.css.left--;
      })
      break;
    case "ArrowRight":
      if(!node) return;
      currentNodeElements.value.forEach(item=>{
        item.css.left++;
      })
      break;
    case "ArrowUp":
      if(!node) return;
      currentNodeElements.value.forEach(item=>{
        item.css.top--;
      })
      break;
    case "ArrowDown":
      if(!node) return;
      currentNodeElements.value.forEach(item=>{
        item.css.top++;
      })
      break;
  }
}

const keyUp = (e : KeyboardEvent) => {
  console.log(e.code)
  const node = currentNodeElements.value[0];
  switch (e.code) {
    case "ArrowLeft":
    case "ArrowRight":
    case "ArrowUp":
    case "ArrowDown":
      if(!node) return;
      saveHistory('微调节点');
      break;
    case "Delete":
      deleteCurrentNodeElements();
      break;
    case "Space":
      isSpace.value = false;
      e.preventDefault();
      break
    case "AltLeft":
    case "AltRight":
      isAlt.value = false;
      break;
    case "ControlLeft":
    case "ControlRight":
      isControl.value = false;
      break;
    case "ShiftLeft":
    case "ShiftRight":
      isShift.value = false;
      break;
    case "KeyZ":
      console.log(isShift.value,isControl.value,isAlt.value)
      if(isControl.value && isShift.value){
        redo();
        break;
      }
      if(isControl.value){
        undo();
      }
      break;
    case "KeyV":
      if(isControl.value){
        stickupData();
      }
      break;
    case "KeyC":
      if(isControl.value){
        copyCurrentNodeElementsToStickup();
        document.querySelector('.edit-content-component').focus();
        isControl.value = false;
      }
      break;
  }
}

const handleScroll = (e) => {
  if (!isAlt.value) {
    return;
  }
  // 阻止默认的滚动行为
  e.preventDefault();

  // 判断滚轮方向
  var delta = Math.sign(e.deltaY);
  if (delta > 0) {
    // 向下滚动
    console.log('向下滚动');
    showScaleInput.value = +showScaleInput.value - 10;
  } else if (delta < 0) {
    // 向上滚动
    console.log('向上滚动');
    showScaleInput.value = +showScaleInput.value + 10;
  }
  setCanvasSize();
}



function getCurrentNodeElementStyle(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  const showWidth = node.css.width===0?tNode.width:node.css.width;
  const showHeight = node.css.height===0?tNode.height:node.css.height;
  const {left,top} = node.css.dynamicLocation?tNode.css:node.css;
  return {
    "left": left * showScale.value/100 + 'px',
    "top": top * showScale.value/100 + 'px',
    "width": showWidth * showScale.value/100 + 'px',
    "height": showHeight * showScale.value/100 + 'px',
    color: node.css.color,
    boxSizing: 'border-box',
    "border-radius": node.css.borderRadius* showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)` + (node.css.angle ? `rotate(${node.css.angle}deg)` : ''),
  }
}

function getCurrentNodeElementImageStyle(node : NodeElement){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  const showWidth = node.css.width===0?tNode.width:node.css.width;
  const showHeight = node.css.height===0?tNode.height:node.css.height;
  let tFont = '';
  let tFontSize = 30;
  if(node.resourceType === 'text' && !node.css.fontSize){
    tFont = node.css.font.replace(/(\d+)r?px/g, (r, fontSize) => {
      if (r.indexOf('r') !== -1) {
        tFontSize = (+fontSize) * showScale.value/100;
        return tFontSize + 'px';
      }
      tFontSize = +fontSize;
      return r
    })
  }else{
    tFontSize = node.css.fontSize * showScale.value/100;
    tFont = `${tFontSize}px ${node.css.fontFamily}`
  }
  return {
    top: '-1px',
    font: tFont,
    color: node.css.color,
    boxSizing: 'border-box',
    opacity: 0.5,
    "border-radius": node.css.borderRadius* showScale.value/100 + 'px',
    border: `${node.css.borderWidth}rpx solid ${node.css.borderColor}`,
    boxShadow: `${node.css.shadowOffsetX}rpx ${node.css.shadowOffsetY}rpx ${node.css.shadowBlur}rpx ${node.css.shadowColor}`,
  }
}



function getLeftLine(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  let {left,top,width,height} = tNode.css;
  return {
    "left": node.css.left * showScale.value/100 + 'px',
    "top": '0px',
    "height": '' + drawData.value.height * showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)`,
  }
}

function getRightLine(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  let {left,top,width,height} = tNode.css;
  return {
    "left": node.css.left * showScale.value/100 + tNode.width * showScale.value/100  + 'px',
    "top": '0px',
    "height": '' + drawData.value.height * showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)`,
  }
}
function getMiddleLine(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  let {left,top,width,height} = tNode.css;
  return {
    "left": node.css.left * showScale.value/100 + tNode.width * showScale.value/100 * 0.5  + 'px',
    "top": '0px',
    "height": '' + drawData.value.height * showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)`,
  }
}
function getTopLine(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  let {left,top,width,height} = tNode.css;
  return {
    "left": '0px',
    "top": node.css.top * showScale.value/100 + 'px',
    "width": '' + drawData.value.width * showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)`,
  }
}
function getBottomLine(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  let {left,top,width,height} = tNode.css;
  return {
    "left": '0px',
    "top": node.css.top * showScale.value/100 + tNode.height * showScale.value/100 + 'px',
    "width": '' + drawData.value.width * showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)`,
  }
}

function getHMiddleLine(node){
  let tNode = node;
  showNodeElements.value.forEach(showNode=>{
    if(showNode.id === node.id){
      tNode = showNode;
    }
  })
  let {left,top,width,height} = tNode.css;
  return {
    "left": '0px',
    "top": node.css.top * showScale.value/100 + tNode.height * showScale.value/100 * 0.5  + 'px',
    "width": '' + drawData.value.width * showScale.value/100 + 'px',
    "transform": `translate(${boxMoveXy.value.x}px,${boxMoveXy.value.y}px)`,
  }
}




function debounce(fn, delay) {
  var timer;
  return function() {
    timer && clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, arguments)
    }, delay);
  }
}

//重新设置画布大小
const setCanvasSize = debounce(() => {
  showScale.value = showScaleInput.value;
  ruler.value.updateRuler();
  draw();
},100)


/**
 * 导出数据
 */
const exportData = () => {
  const data = copyObj(drawData.value)
  data.nodeElements.forEach((item)=>{
    delete item.width;
    delete item.height;
    delete item.id;
    delete item.moveData;
  })
  uni.setClipboardData({
    data: JSON.stringify(data, null, 2),
    success: function () {
      uni.showToast({
        title: '复制成功',
      });
    },
    fail:function () {
      uni.showToast({
        title: '复制失败',
      });
    }
  });
}

/**
 * 导出图片
 */
const downImageData = ()=>{

  if(imageData === ''){
    uni.showToast({
      title: '没有图片数据',
    })
    return;
  }
  function downloadImage(url, filename) {
    var link = document.createElement('a');
    link.href = url;
    link.download = filename;
    link.target = '_blank';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }
  downloadImage(imageData,`image${Date.now()}.png`);
}

const componentPropsShow = ref(false);
watchEffect(()=>{
  componentPropsShow.value = currentNodeElements.value.length > 0;
})

/**
 * 组件点击
 * @param clickItems
 */
const componentClick = (clickItems) => {
  console.log('componentClick',clickItems)
  if(moveAndNode){
    return;
  }
  if(clickItems.length === 0){
    currentNodeElements.value = [];
    return;
  }
  console.log(keyDownLeftTopRef.value,'keyDownLeftTopRef');
  keyDownLeftTopRef.value.$el.focus({
    preventScroll: true
  });
  const items = [];
  clickItems.forEach(item=>{
    function _run(node: NodeElement) {
      if(node.id === item.id){
        items.push(node);
        return;
      }
      if (node.resourceType !== 'group') {
        return;
      }
      if (!node.children || node.children.length === 0) {
        return;
      }
      node.children.forEach((item)=>{
        _run(item);
      })
    }
    drawData.value.nodeElements.forEach((item)=>{
      _run(item);
    })
  })
  if(isControl.value){
    const index = currentNodeElements.value.indexOf(items[0]);
    if(index === -1){
      currentNodeElements.value.push(items[0]);
    }else {
      currentNodeElements.value.splice(index,1);
    }
  }else{
    currentNodeElements.value = [items[0]];
  }

}

let keyDownLeftTopRef = ref('');


let editContentWidth = ref('');
let editContentHeight = ref('');
let editWidth = 0;
let editHeight = 0;
var ruler = ref<Ruler>();
const init = async () => {
  //初始化自适应显示
  adaptiveShow();

  //事件监听
  let editContentComponent = document.querySelector('.edit-content-component');

  editContentComponent.addEventListener("keydown", keyDown);
  editContentComponent.addEventListener("keyup", keyUp);
  editContentComponent.addEventListener("wheel", handleScroll,{passive: false});

  editContentComponent.addEventListener("mousedown", selectedDown);
  editContentComponent.addEventListener("mousemove", selectedMove);
  editContentComponent.addEventListener("mouseup", selectedUp);
  window.addEventListener('resize', adaptiveShow);

  ruler.value = new Ruler();
}


onMounted(()=>{
  drawData.value = templateDatas[0];
  nodeElementGenerateId();
  setHadaCanvas(hadaCanvas.value);
  setHistoryWindow(historyWindow.value);
  init();
  saveHistory('初始化');
  setTimeout(()=>{
    draw();
  },500)
  watchEffect(()=>{
    ruler.value.updateRuler();
  })
})




const canvasBoxClick = async (e) => {

  const {x,y} = e.detail;
  const nodes = await hadaCanvas.value.getNodeElementByPoint(x,y);
  console.log(nodes,'canvasBoxClick')
  componentClick(nodes);
}
const nodeClick = (node) => {
  componentClick(node);
}

const isSelected = (data) => {
  return currentNodeElements.value.some(item=>{
    if(item.id === data.id){
      return true
    }
  })
}

const isSelectedGroup = (group:NodeElement) => {
  return  group.children.every(item=>isSelected(item))
}



let imageData = '';



const change = (imageDataTemp, showData, showNodes) => {
  actualMultiple.value = 1/showData.zoom;
  function getShowNodes() {
    const nodes = [];
    function _run(node: NodeElement) {
      nodes.push(node);
      if (node.resourceType !== 'group') {
        return;
      }
      if (!node.children || node.children.length === 0) {
        return;
      }
      node.children.forEach((item)=>{
        _run(item);
      })
    }
    showNodes.forEach((item)=>{
      _run(item);
    })

    return nodes;
  }
  showNodeElements.value = getShowNodes();
  imageData = imageDataTemp;
}

const drawError = (error: Error) => {
  ElMessage.error('绘制错误：' + JSON.stringify(error) + '详情请查看控制台');
  console.error(error);
}


let editor = reactive({
  leftMouseClick: false,
  cursor: -1,
  node: null,
  left: 0,
  top: 0,
  width: 0,
  height: 0,
  angle: 0
});
const editorDown = (e : MouseEvent,cursor,item)=>{
  if(item.css.width === 0 && (cursor >= 0 && cursor <= 7)){
    return;
  }
  editor.leftMouseClick = true;

  showNodeElements.value.forEach(item1=>{
    if(item1.id === item.id){
      console.log(item1,'item1')
      editor.width = item1.width;
      editor.height = item1.height;
    }
  })

  editor.top = item.css.top;
  editor.left = item.css.left;
  editor.angle = item.css.angle??0;
  editor.cursor = cursor;
  editor.node = item;
}

let lastPointermove = { x: 0, y: 0 };
let current = {x:0,y:0};
let origin = {x:0,y:0};
let box = {x:0,y:0,width:0,height:0,rotate:0};


function getAngle(a, b) {
  const x = a.x - b.x
  const y = a.y - b.y;
  return 180 * Math.atan2(y, x) / Math.PI;
}

function clacInitAnglePoint(angle, current, origin) {
  // 原始坐标点
  const point = current;

// 旋转中心坐标
  const center = origin;

// 旋转角度（弧度）
  const angleRadians = angle * Math.PI/180;

// 计算旋转后的坐标
  const x = center.x + (point.x - center.x) * Math.cos(angleRadians) - (point.y - center.y) * Math.sin(angleRadians);
  const y = center.y + (point.x - center.x) * Math.sin(angleRadians) + (point.y - center.y) * Math.cos(angleRadians);
  return { x, y };
}

/**
 * 获得旋转夹角
 */
function getRotate(moveX,moveY) {
  current = { x: lastPointermove.x + moveX, y: lastPointermove.y + moveY };
  //根据初始角度计算转换坐标
  const angle1 = getAngle(origin, current);
  const angle2 = getAngle(origin, lastPointermove);

  let angle = angle1 - angle2;
  let cangle = editor.angle;
  cangle = (cangle + angle + 360) % 360;

  return Math.floor(cangle);
}

const editorMove = ({moveX,moveY})=>{
  let widthDiff = editor.width;
  moveY = moveY * actualMultiple.value;
  moveX = moveX * actualMultiple.value;
  if(editor.leftMouseClick){
    if(editor.cursor === 4){
      editor.node.css.height = editor.height - moveY;
      editor.node.css.top = editor.top + moveY;
    }else if(editor.cursor === 6){
      editor.node.css.width = widthDiff + moveX;
    }else if(editor.cursor === 0){
      editor.node.css.height = editor.height + moveY;
    }else if(editor.cursor === 2){
      editor.node.css.width = widthDiff - moveX;
      editor.node.css.left = editor.left + moveX;
    }else if(editor.cursor === 1){
      editor.node.css.width = widthDiff - moveX;
      editor.node.css.height = editor.height + moveY;
      editor.node.css.left = editor.left + moveX;
    }else if(editor.cursor === 3){
      editor.node.css.width = widthDiff - moveX;
      editor.node.css.height = editor.height - moveY;
      editor.node.css.left = editor.left + moveX;
      editor.node.css.top = editor.top + moveY;
    }else if(editor.cursor === 5){
      editor.node.css.width = widthDiff + moveX;
      editor.node.css.height = editor.height - moveY;
      editor.node.css.top = editor.top + moveY;
    }else if(editor.cursor === 7){
      editor.node.css.width = widthDiff + moveX;
      editor.node.css.height = editor.height + moveY;
    }else if(editor.cursor === 8){
      //拖动坐标转角度
      editor.node.css.angle = getRotate(moveX,moveY);
    }
    if(editor.cursor >= 0 && editor.cursor <= 7){
      editor.node.css.width = Math.max(editor.node.css.width, 10);
      editor.node.css.height = Math.max(editor.node.css.height, 10);

    }

    return true;
  }
}

function addBackgroundColor(node) {
  node.css.backgroundColor.push('rgba(255,255,255,1)');
}
function removeColor(node) {
  if(node.css.backgroundColor.length < 3){
    ElMessageBox.alert('渐变色最少需要两个颜色')
    return;
  }
  node.css.backgroundColor.pop();
}
function enableGradient(e,node){
  if(e){
    node.css.backgroundColor = [node.css.backgroundColor??'rgba(255,255,255,1)'];
    node.css.backgroundColor.push('rgba(255,255,255,0)');
    node.css.backgroundColorGradientDirection = 'to bottom';
    saveHistory('启用渐变');
  }else{
    node.css.backgroundColor = node.css.backgroundColor[0];
    saveHistory('取消渐变');
  }

}


</script>

<style lang="scss">
@import "alignLine";
@import "ruler";

@import "//at.alicdn.com/t/c/font_3585469_l0g3isbgp9a.css";




.move-node{
  pointer-events: none;
}

.menu-list{
  display: flex;
  flex-direction: column;
  .menu-item{
    display: flex;
    padding: 20rpx;
    border-radius: 10rpx;
  }
  .menu-item:hover{
    cursor: pointer;
    background: #f2f2f2;
  }
}

.content {
  display: flex;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  flex-direction: column;

  .history-btn{
    cursor: pointer;
    padding: 10rpx;
    border-radius: 10rpx;
  }
  .history-btn:hover{
    background: #f2f2f2;
  }
  .history-window{
    position: absolute;
    top: 114rpx;
    transform: translateX(50%);
    z-index: 1;
    background: #ffffff;
    padding: 20rpx;
    border-radius: 10rpx;
    display: flex;
    flex-direction: column;
    box-shadow: #757575 0 0 4rpx;
    cursor: default;
    .history-top{
      display: flex;
      align-items: center;
      justify-content: space-between;
      .close{
        cursor: pointer;
      }
    }
    .history-list{
      display: flex;
      flex-direction: column;
      overflow-y: auto;
      max-height: 300rpx;
      width: 400rpx;
      .history-item{
        display: flex;
        padding: 10rpx;
        border-radius: 10rpx;
        cursor: pointer;
        .name{
          margin-left: 10rpx;
        }
      }
      .history-item:hover{
        background: #f2f2f2;
      }
    }

  }

  .fonts-box{
    display: flex;
    flex-direction: column;
    padding: 20rpx;
    flex: 1;
    overflow-y: auto;
    .box-card{
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
    .fonts-list{
      display: flex;
      flex-direction: column;
      .component-name{
        display: inline-flex;
      }
      .fonts-item{
        display: flex;
        flex-direction: column;
        border: #f2f2f2 1px solid;
        padding: 10rpx;
        border-radius: 10rpx;
        margin-bottom: 20rpx;
        .font-top{
          display: flex;
          justify-content: space-between;
          align-items: center;
          .font-delete{
            cursor: pointer;
            width: 40rpx;
            height: 40rpx;
            margin: 10rpx;
            border-radius: 50%;
            border: #ababab 1px solid;
            display: flex;
            align-items: center;
            justify-content: center;
          }
        }
        .font-content{
          padding: 0 10rpx;
        }
        .font-name ,.font-url{
          display: flex;
          padding: 10rpx 0;
        }
        input{
          background: #f2f2f2;
          padding: 5rpx;
        }
      }
      .fonts-item:last-child{
        margin-bottom: 0;
      }
    }
    .card-header{
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .card-body{

    }

  }
  .code{
    padding: 20rpx;
  }
  .tools-menu{;
    padding: 10rpx;
    display: flex;
    align-items: center;

    .file-menu-box{
      margin: 0 20rpx;
      width: 70rpx;
      .file-menu{
        width: 50rpx;
        display: flex;
        padding: 10rpx;
        margin: 10rpx;
        border-radius: 10rpx;
      }
      .file-menu:hover{
        cursor: pointer;
        background: #f2f2f2;
      }

    }

    .edit-width-height{
      display: flex;
      width: 100%;
      padding-left: 690rpx;
      transition: padding-left 0.3s;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      .top-btn{
        cursor: pointer;
        padding: 10rpx;
        border-radius: 10rpx;
      }
      .top-btn:hover{
        background: #f2f2f2;
      }
      .edit-input{
        flex: 1;
        display: flex;
        margin-left: 10rpx;
        >view{
          display: flex;
          justify-content: center;
          align-items: center;
          margin-left: 10rpx;
          input{
            background: #f2f2f2;
            color: #000;
            padding: 10rpx;
            border-radius: 10rpx;
            width: 150rpx;

          }
        }
        .align-box{
          display: flex;
          .align-btn{
            cursor: pointer;
            padding: 10rpx;
            font-size: 40rpx;
            border-radius: 10rpx;
            .iconfont{
              font-size: 40rpx;
            }
          }
          .align-btn:hover{
            background: #f2f2f2;
          }
        }
        .align-box.disabled{
          .iconfont{
            color: #adadad;
          }
        }
      }
    }
  }

  .ep-wrapper {
    flex: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    overflow: auto;

    .edit-wrapper{
      display: flex;
      flex: 1;
      overflow: hidden;
      .left-menu{
        position: relative;
        display: flex;
        border-top: #f2f2f2 1px solid;
        background: #fff;
        .left-view{
          background: #fff;
          z-index: 1;
          border-right: #f2f2f2 1px solid;
        }
      }
      .left-menu-box{
        display: flex;
        font-size: 36rpx;
        margin: 20rpx;
        width: 70rpx;
        height: 100rpx;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        padding: 20rpx;
        border-radius: 10rpx;
        background: #fff;
        .icon{
          color: #222529;
          margin-bottom: 4px;
          font-size: 24px;
        }
        .left-menu-name{
          font-size: 24rpx;
          color: #7f8792;
        }
      }
      .left-menu-box:hover{
        background: #f2f2f2;
        cursor: pointer;
      }
      .left-menu-box.active{
        background: #f2f2f2;
      }

      .leftMenuActive{
        display: flex;
        transition: all 0.3s;
        width: 650rpx;
        margin-left: -650rpx;
        height: 100%;
        flex-direction: column;
        .shrink{
          position: absolute;
          top: 40%;
          left: calc(100% - 2px);
          background: url("/static/leftMenuClose.svg") no-repeat;
          width: 15px;
          height: 100px;
          cursor: pointer;
          z-index: 1;
          transform: translateY(-50%);
        }
        .allComponent{
          flex: 1;
          display: flex;
          flex-direction: column;
          overflow: hidden;
        }
      }
      .leftMenuActive.open{
        //width: 650rpx;
        margin-left: 0;
      }



      .template-list{
        padding: 10rpx;
        display: flex;
        height: 300rpx;
        overflow-y: auto;
        flex-direction: column;
        .template-item{
          cursor: pointer;
          padding: 20rpx 10rpx;
          border-bottom: #f2f2f2 1px solid;
        }
      }
      .all-component-list{
        padding: 10rpx;
        display: flex;
        flex-direction: column;
        height: 100%;
        overflow-y: auto;
        .component-item{
          flex: 1;
          cursor: pointer;
          border-bottom: #f2f2f2 1px solid;
          display: flex;
          align-items: center;
          background: #fff;
          .component-name{
            display: inline-flex;
          }
          .data{
            flex: 1;
            display: flex;
            justify-content: space-between;
            margin: 10rpx;
            padding: 10rpx;
            .data-content{
              display: flex;
              flex-direction: column;
            }
          }
          .data.selected{
            background: #000000CC;
            color: #FFFFFF;
            border-radius: 20rpx;
          }
          .group{

            flex: 1;
            display: flex;
            justify-content: space-between;
            flex-direction: column;

            .group-content{
              display: flex;
              justify-content: space-between;
              margin: 10rpx;
              padding: 10rpx;
              border-radius: 10rpx;
            }
            .group-content.selected{
              background: rgba(79, 77, 77, 0.8);
              color: #FFFFFF;
            }
            .group-data{
              margin: 0 10rpx;
              padding: 0 10rpx;
              .data{
                flex: 1;
                display: flex;
                justify-content: space-between;
                margin: 10rpx 0;
                padding: 10rpx;
                .data-content{
                  display: flex;
                  flex-direction: column;
                }
              }
              .data.selected{
                background: #000000CC;
                color: #FFFFFF;
                border-radius: 20rpx;
              }
            }

          }

        }


      }
      .component-list{
        padding: 10rpx;
        flex: 1;
        display: grid;
        grid-template-columns: 1fr 1fr 1fr;
        grid-gap: 10rpx;

        .add-item{
          width: 200rpx;
          height: 170rpx;
          position: relative;
          display: flex;
          flex-direction: column;
          align-items: center;
          justify-content: center;
          font: 400 24rpx / 1.5 "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB","WenQuanYi Micro Hei",Arial, sans-serif, Apple Color Emoji,Segoe UI Emoji;
          line-height: 36rpx;
          color: #4c535c;
          text-align: center;
          background-color: rgba(241, 242, 244, 0.8);
          border-radius: 16rpx;
          cursor: pointer;
          user-select: none;
        }
        .add-item:hover{
          background-color: rgba(241, 242, 244, 1);
        }
        .icons{
          cursor: default;
          padding-left: 10rpx;
          box-sizing: border-box;
          .add-icons{
            display: flex;
            flex-wrap: wrap;
            >view{
              margin: 10rpx;
              cursor: pointer;
            }
          }

        }

      }
      .edit-content{
        flex: 4;
        display: flex;
        overflow: hidden;
        flex-direction: column;
        border: #f2f2f2 1px solid;
        justify-content: center;
        align-items: center;

        .edit-content-component{
          width: 100%;
          //width: v-bind(editContentWidth);
          height: 100%;
          height: v-bind(editContentHeight);
          position: relative;
          overflow: auto;
          background: #f4f5f7;

          .canvas-box{
            background-color: #fff;
            background-image: linear-gradient(to top right,#ccc 25%,transparent 0,transparent 75%,#ccc 0,#ccc),linear-gradient(to top right,#ccc 25%,transparent 0,transparent 75%,#ccc 0,#ccc);
            background-position: 0 0,8px 8px;
            background-size: 16px 16px;
            position: absolute;
            top: 0;
            left: 0;
          }

        }
        .pointer{
          cursor: pointer;
        }
      }

      .component-props{
        width: 750rpx;
        background: #fff;
        z-index: 5;
        transition: all 0.3s;
        padding: 10rpx 20rpx;
        overflow-y: scroll;
        overflow-x: auto;
        display: flex;
        flex-direction: column;
        box-shadow: #cccccc 0 0 10rpx;
        border-top: #f2f2f2 1px solid;
        .props{
          display: flex;
          flex-direction: column;
          .prop-item.dynamicLocation{
            align-items: flex-start;
            .prop-name{
              margin-top: 10rpx;
            }
          }
          .prop-item{
            display: flex;
            flex: 1;
            align-items: center;
            padding: 5rpx 0;

            .prop-name{
              width: 200rpx;
            }
            input{
              margin-right: 20rpx;
              flex: 1;
              padding: 4rpx 10rpx;
              //background: #f2f2f2;
              border: #f2f2f2 1px solid;
              border-radius: 10rpx;
            }
            input:hover{
              background: #f2f2f2;
            }
          }
        }
      }

      //.component-props.open{
      //  width: 750rpx;
      //}

    }

  }
}

.container {
  position: absolute;
  height: 100vh;
  z-index: 1;
  top: 0;
  //background: #000;
  //overflow: hidden;
  user-select: none;
}

.background-color{
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex: 1;
  .background-color-content{
    flex: 1;
    display: flex;
    flex-wrap: wrap;
    gap: 10rpx;
    align-items: center;
    .backgroundColorGradientDirection{
      display: flex;
      align-items: center;
    }
    .background-color-gradient-add{
      padding: 8rpx 10rpx;
      border-radius: 8rpx;
      cursor: pointer;
      &:hover{
        background: #f2f2f2;
      }
    }
  }
  .backgroundColorGradient{
    width: 200rpx;
    display: flex;
    align-items: center;
    justify-content: space-between;
    .background-color-gradient-delete{
      padding: 8rpx 10rpx;
      border-radius: 8rpx;
      cursor: pointer;
      &:hover{
        background: #f2f2f2;
      }
    }
  }
}

</style>
